#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
数据可视化模块
专门负责图表绘制和可视化功能
"""

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False

class EpidemicDataVisualizer:
    """疫情数据可视化器"""
    
    def __init__(self):
        """初始化可视化器"""
        self.setup_style()
    
    def setup_style(self):
        """设置图表样式"""
        plt.style.use('default')
        plt.rcParams['font.size'] = 10
        plt.rcParams['axes.titlesize'] = 12
        plt.rcParams['axes.labelsize'] = 10
    
    def plot_daily_cases(self, daily_stats):
        """绘制每日确诊病例折线图"""
        if daily_stats is None:
            print("❌ 请先提供每日统计数据")
            return
        
        print("\n" + "="*60)
        print("📊 生成确诊病例折线图")
        print("="*60)
        
        # 创建图表
        fig, axes = plt.subplots(2, 2, figsize=(18, 14))
        fig.suptitle('香港各区疫情数据 - 每日确诊病例趋势分析\nHong Kong District Epidemic Data - Daily Confirmed Cases Trend', 
                    fontsize=16, fontweight='bold', y=0.95)
        
        # 设置背景色
        fig.patch.set_facecolor('#f8f9fa')
        
        # 1. 每日新增确诊趋势
        ax1 = axes[0, 0]
        ax1.plot(daily_stats['报告日期'], daily_stats['新增确诊'], 
                color='#FF6B6B', linewidth=2.5, marker='o', markersize=3, 
                markerfacecolor='white', markeredgecolor='#FF6B6B', markeredgewidth=1.5)
        ax1.set_title('每日新增确诊病例\nDaily New Confirmed Cases', fontsize=14, fontweight='bold', pad=15)
        ax1.set_xlabel('日期 Date', fontsize=11, fontweight='bold')
        ax1.set_ylabel('新增确诊数 New Cases', fontsize=11, fontweight='bold')
        ax1.grid(True, alpha=0.2, linestyle='--')
        ax1.tick_params(axis='x', rotation=45, labelsize=9)
        ax1.tick_params(axis='y', labelsize=9)
        ax1.set_facecolor('#ffffff')
        
        # 添加最大值标注
        max_new = daily_stats['新增确诊'].max()
        max_date = daily_stats.loc[daily_stats['新增确诊'].idxmax(), '报告日期']
        ax1.annotate(f'单日峰值\n{max_new:,}例\n{max_date.strftime("%Y-%m-%d")}', 
                    xy=(max_date, max_new), xytext=(10, 10), textcoords='offset points',
                    bbox=dict(boxstyle='round,pad=0.5', facecolor='#FF6B6B', alpha=0.8),
                    fontsize=9, color='white', fontweight='bold',
                    arrowprops=dict(arrowstyle='->', color='#FF6B6B', lw=1.5))
        
        # 2. 累计确诊趋势
        ax2 = axes[0, 1]
        ax2.plot(daily_stats['报告日期'], daily_stats['累计确诊'], 
                color='#4ECDC4', linewidth=2.5, marker='s', markersize=3,
                markerfacecolor='white', markeredgecolor='#4ECDC4', markeredgewidth=1.5)
        ax2.set_title('累计确诊病例\nTotal Confirmed Cases', fontsize=14, fontweight='bold', pad=15)
        ax2.set_xlabel('日期 Date', fontsize=11, fontweight='bold')
        ax2.set_ylabel('累计确诊数 Total Cases', fontsize=11, fontweight='bold')
        ax2.grid(True, alpha=0.2, linestyle='--')
        ax2.tick_params(axis='x', rotation=45, labelsize=9)
        ax2.tick_params(axis='y', labelsize=9)
        ax2.set_facecolor('#ffffff')
        
        # 添加最终值标注
        final_total = daily_stats['累计确诊'].iloc[-1]
        final_date = daily_stats['报告日期'].iloc[-1]
        ax2.annotate(f'累计确诊总数\n{final_total:,}例\n{final_date.strftime("%Y-%m-%d")}', 
                    xy=(final_date, final_total), xytext=(-50, 20), textcoords='offset points',
                    bbox=dict(boxstyle='round,pad=0.5', facecolor='#4ECDC4', alpha=0.8),
                    fontsize=9, color='white', fontweight='bold',
                    arrowprops=dict(arrowstyle='->', color='#4ECDC4', lw=1.5))
        
        # 3. 现存确诊趋势
        ax3 = axes[1, 0]
        ax3.plot(daily_stats['报告日期'], daily_stats['现存确诊'], 
                color='#45B7D1', linewidth=2.5, marker='^', markersize=3,
                markerfacecolor='white', markeredgecolor='#45B7D1', markeredgewidth=1.5)
        ax3.set_title('现存确诊病例\nCurrent Confirmed Cases', fontsize=14, fontweight='bold', pad=15)
        ax3.set_xlabel('日期 Date', fontsize=11, fontweight='bold')
        ax3.set_ylabel('现存确诊数 Current Cases', fontsize=11, fontweight='bold')
        ax3.grid(True, alpha=0.2, linestyle='--')
        ax3.tick_params(axis='x', rotation=45, labelsize=9)
        ax3.tick_params(axis='y', labelsize=9)
        ax3.set_facecolor('#ffffff')
        
        # 4. 康复和死亡趋势
        ax4 = axes[1, 1]
        line1 = ax4.plot(daily_stats['报告日期'], daily_stats['累计康复'], 
                        color='#96CEB4', linewidth=2.5, label='累计康复\nTotal Recovered', 
                        marker='o', markersize=3, markerfacecolor='white', 
                        markeredgecolor='#96CEB4', markeredgewidth=1.5)
        line2 = ax4.plot(daily_stats['报告日期'], daily_stats['累计死亡'], 
                        color='#FFEAA7', linewidth=2.5, label='累计死亡\nTotal Deaths', 
                        marker='s', markersize=3, markerfacecolor='white', 
                        markeredgecolor='#FFEAA7', markeredgewidth=1.5)
        ax4.set_title('康复与死亡趋势\nRecovery and Death Trends', fontsize=14, fontweight='bold', pad=15)
        ax4.set_xlabel('日期 Date', fontsize=11, fontweight='bold')
        ax4.set_ylabel('人数 Number of People', fontsize=11, fontweight='bold')
        ax4.legend(loc='upper left', fontsize=10, framealpha=0.9)
        ax4.grid(True, alpha=0.2, linestyle='--')
        ax4.tick_params(axis='x', rotation=45, labelsize=9)
        ax4.tick_params(axis='y', labelsize=9)
        ax4.set_facecolor('#ffffff')
        
        # 添加数据来源和生成时间
        fig.text(0.02, 0.02, f'数据来源: 香港各区疫情数据 | 生成时间: {pd.Timestamp.now().strftime("%Y-%m-%d %H:%M")}', 
                fontsize=8, style='italic', color='#666666')
        
        # 调整布局
        plt.tight_layout()
        plt.subplots_adjust(top=0.92, bottom=0.08)
        
        # 保存图表
        plt.savefig('香港疫情数据_每日趋势图.png', dpi=300, bbox_inches='tight', 
                   facecolor='#f8f9fa', edgecolor='none')
        print("✅ 图表已保存为: 香港疫情数据_每日趋势图.png")
        
        # 显示图表
        plt.show()
        
        # 创建详细趋势图
        self.plot_detailed_trends(daily_stats)
    
    def plot_detailed_trends(self, daily_stats):
        """绘制详细趋势图"""
        # 创建大图显示关键指标
        fig, axes = plt.subplots(3, 1, figsize=(18, 16))
        fig.suptitle('香港疫情数据详细趋势分析\nHong Kong Epidemic Data Detailed Trend Analysis', 
                    fontsize=18, fontweight='bold', y=0.95)
        
        # 设置背景色
        fig.patch.set_facecolor('#f8f9fa')
        
        # 1. 新增确诊趋势（带7日移动平均）
        ax1 = axes[0]
        daily_stats['新增确诊_7日平均'] = daily_stats['新增确诊'].rolling(window=7).mean()
        
        # 绘制每日新增数据
        ax1.plot(daily_stats['报告日期'], daily_stats['新增确诊'], 
                color='#FF6B6B', alpha=0.6, label='每日新增\nDaily New Cases', 
                linewidth=1.5, marker='o', markersize=2)
        
        # 绘制7日移动平均线
        ax1.plot(daily_stats['报告日期'], daily_stats['新增确诊_7日平均'], 
                color='#FF4757', linewidth=3, label='7日移动平均\n7-Day Moving Average')
        
        ax1.set_title('每日新增确诊病例趋势分析\nDaily New Confirmed Cases Trend Analysis', 
                     fontsize=14, fontweight='bold', pad=20)
        ax1.set_ylabel('新增确诊数 New Cases', fontsize=11, fontweight='bold')
        ax1.legend(loc='upper right', fontsize=10, framealpha=0.9)
        ax1.grid(True, alpha=0.2, linestyle='--')
        ax1.tick_params(axis='x', rotation=45, labelsize=9)
        ax1.tick_params(axis='y', labelsize=9)
        ax1.set_facecolor('#ffffff')
        
        # 添加峰值标注
        max_new = daily_stats['新增确诊'].max()
        max_date = daily_stats.loc[daily_stats['新增确诊'].idxmax(), '报告日期']
        ax1.annotate(f'单日新增峰值\n{max_new:,}例\n{max_date.strftime("%Y-%m-%d")}', 
                    xy=(max_date, max_new), xytext=(20, 20), textcoords='offset points',
                    bbox=dict(boxstyle='round,pad=0.5', facecolor='#FF4757', alpha=0.9),
                    fontsize=9, color='white', fontweight='bold',
                    arrowprops=dict(arrowstyle='->', color='#FF4757', lw=2))
        
        # 2. 累计确诊和康复对比
        ax2 = axes[1]
        line1 = ax2.plot(daily_stats['报告日期'], daily_stats['累计确诊'], 
                        color='#4ECDC4', linewidth=2.5, label='累计确诊\nTotal Confirmed Cases',
                        marker='s', markersize=3, markerfacecolor='white', 
                        markeredgecolor='#4ECDC4', markeredgewidth=1.5)
        line2 = ax2.plot(daily_stats['报告日期'], daily_stats['累计康复'], 
                        color='#96CEB4', linewidth=2.5, label='累计康复\nTotal Recovered Cases',
                        marker='o', markersize=3, markerfacecolor='white', 
                        markeredgecolor='#96CEB4', markeredgewidth=1.5)
        
        ax2.set_title('累计确诊与康复对比分析\nTotal Confirmed vs Recovered Cases Comparison', 
                     fontsize=14, fontweight='bold', pad=20)
        ax2.set_ylabel('人数 Number of People', fontsize=11, fontweight='bold')
        ax2.legend(loc='upper left', fontsize=10, framealpha=0.9)
        ax2.grid(True, alpha=0.2, linestyle='--')
        ax2.tick_params(axis='x', rotation=45, labelsize=9)
        ax2.tick_params(axis='y', labelsize=9)
        ax2.set_facecolor('#ffffff')
        
        # 添加康复率标注
        final_confirmed = daily_stats['累计确诊'].iloc[-1]
        final_recovered = daily_stats['累计康复'].iloc[-1]
        recovery_rate = (final_recovered / final_confirmed * 100) if final_confirmed > 0 else 0
        ax2.annotate(f'累计康复率\n{recovery_rate:.1f}%', 
                    xy=(daily_stats['报告日期'].iloc[-1], final_recovered), 
                    xytext=(-50, 30), textcoords='offset points',
                    bbox=dict(boxstyle='round,pad=0.5', facecolor='#96CEB4', alpha=0.9),
                    fontsize=9, color='white', fontweight='bold',
                    arrowprops=dict(arrowstyle='->', color='#96CEB4', lw=2))
        
        # 3. 死亡率趋势
        ax3 = axes[2]
        daily_stats['死亡率'] = (daily_stats['累计死亡'] / daily_stats['累计确诊'] * 100).fillna(0)
        
        ax3.plot(daily_stats['报告日期'], daily_stats['死亡率'], 
                color='#FFA502', linewidth=2.5, marker='o', markersize=3,
                markerfacecolor='white', markeredgecolor='#FFA502', markeredgewidth=1.5)
        ax3.set_title('死亡率趋势分析\nDeath Rate Trend Analysis (%)', 
                     fontsize=14, fontweight='bold', pad=20)
        ax3.set_xlabel('日期 Date', fontsize=11, fontweight='bold')
        ax3.set_ylabel('死亡率 Death Rate (%)', fontsize=11, fontweight='bold')
        ax3.grid(True, alpha=0.2, linestyle='--')
        ax3.tick_params(axis='x', rotation=45, labelsize=9)
        ax3.tick_params(axis='y', labelsize=9)
        ax3.set_facecolor('#ffffff')
        
        # 添加死亡率标注
        final_death_rate = daily_stats['死亡率'].iloc[-1]
        ax3.annotate(f'累计死亡率\n{final_death_rate:.2f}%', 
                    xy=(daily_stats['报告日期'].iloc[-1], final_death_rate), 
                    xytext=(-50, 10), textcoords='offset points',
                    bbox=dict(boxstyle='round,pad=0.5', facecolor='#FFA502', alpha=0.9),
                    fontsize=9, color='white', fontweight='bold',
                    arrowprops=dict(arrowstyle='->', color='#FFA502', lw=2))
        
        # 添加数据来源和生成时间
        fig.text(0.02, 0.02, f'数据来源: 香港各区疫情数据 | 生成时间: {pd.Timestamp.now().strftime("%Y-%m-%d %H:%M")}', 
                fontsize=8, style='italic', color='#666666')
        
        plt.tight_layout()
        plt.subplots_adjust(top=0.92, bottom=0.08)
        plt.savefig('香港疫情数据_详细趋势分析.png', dpi=300, bbox_inches='tight', 
                   facecolor='#f8f9fa', edgecolor='none')
        print("✅ 详细分析图表已保存为: 香港疫情数据_详细趋势分析.png")
        plt.show()
    
    def plot_regional_comparison(self, regional_stats):
        """绘制各区对比图"""
        if regional_stats is None:
            print("❌ 请先提供各区统计数据")
            return
        
        print("\n" + "="*60)
        print("🏘️ 生成各区对比图表")
        print("="*60)
        
        # 创建图表
        fig, axes = plt.subplots(2, 2, figsize=(18, 14))
        fig.suptitle('香港各区疫情数据对比分析\nHong Kong District Epidemic Data Comparison', 
                    fontsize=16, fontweight='bold', y=0.95)
        
        # 设置背景色
        fig.patch.set_facecolor('#f8f9fa')
        
        # 1. 各区累计确诊柱状图
        ax1 = axes[0, 0]
        top_regions = regional_stats.nlargest(10, '累计确诊')
        bars1 = ax1.bar(range(len(top_regions)), top_regions['累计确诊'], 
                        color='#FF6B6B', alpha=0.8)
        ax1.set_title('各区累计确诊排名 (前10名)\nTop 10 Districts by Total Confirmed Cases', 
                     fontsize=14, fontweight='bold', pad=15)
        ax1.set_xlabel('地区 District', fontsize=11, fontweight='bold')
        ax1.set_ylabel('累计确诊数 Total Cases', fontsize=11, fontweight='bold')
        ax1.set_xticks(range(len(top_regions)))
        ax1.set_xticklabels(top_regions['地区名称'], rotation=45, ha='right')
        ax1.grid(True, alpha=0.2, linestyle='--')
        ax1.set_facecolor('#ffffff')
        
        # 添加数值标签
        for i, bar in enumerate(bars1):
            height = bar.get_height()
            ax1.text(bar.get_x() + bar.get_width()/2., height,
                    f'{int(height):,}', ha='center', va='bottom', fontsize=8)
        
        # 2. 各区发病率对比
        ax2 = axes[0, 1]
        top_incidence = regional_stats.nlargest(10, '发病率(每10万人)')
        bars2 = ax2.bar(range(len(top_incidence)), top_incidence['发病率(每10万人)'], 
                        color='#4ECDC4', alpha=0.8)
        ax2.set_title('各区发病率排名 (前10名)\nTop 10 Districts by Incidence Rate', 
                     fontsize=14, fontweight='bold', pad=15)
        ax2.set_xlabel('地区 District', fontsize=11, fontweight='bold')
        ax2.set_ylabel('发病率(每10万人) Incidence Rate', fontsize=11, fontweight='bold')
        ax2.set_xticks(range(len(top_incidence)))
        ax2.set_xticklabels(top_incidence['地区名称'], rotation=45, ha='right')
        ax2.grid(True, alpha=0.2, linestyle='--')
        ax2.set_facecolor('#ffffff')
        
        # 3. 康复率对比
        ax3 = axes[1, 0]
        top_recovery = regional_stats.nlargest(10, '康复率')
        bars3 = ax3.bar(range(len(top_recovery)), top_recovery['康复率'], 
                        color='#96CEB4', alpha=0.8)
        ax3.set_title('各区康复率排名 (前10名)\nTop 10 Districts by Recovery Rate', 
                     fontsize=14, fontweight='bold', pad=15)
        ax3.set_xlabel('地区 District', fontsize=11, fontweight='bold')
        ax3.set_ylabel('康复率 Recovery Rate (%)', fontsize=11, fontweight='bold')
        ax3.set_xticks(range(len(top_recovery)))
        ax3.set_xticklabels(top_recovery['地区名称'], rotation=45, ha='right')
        ax3.grid(True, alpha=0.2, linestyle='--')
        ax3.set_facecolor('#ffffff')
        
        # 4. 死亡率对比
        ax4 = axes[1, 1]
        top_death = regional_stats.nlargest(10, '死亡率')
        bars4 = ax4.bar(range(len(top_death)), top_death['死亡率'], 
                        color='#FFA502', alpha=0.8)
        ax4.set_title('各区死亡率排名 (前10名)\nTop 10 Districts by Death Rate', 
                     fontsize=14, fontweight='bold', pad=15)
        ax4.set_xlabel('地区 District', fontsize=11, fontweight='bold')
        ax4.set_ylabel('死亡率 Death Rate (%)', fontsize=11, fontweight='bold')
        ax4.set_xticks(range(len(top_death)))
        ax4.set_xticklabels(top_death['地区名称'], rotation=45, ha='right')
        ax4.grid(True, alpha=0.2, linestyle='--')
        ax4.set_facecolor('#ffffff')
        
        # 添加数据来源和生成时间
        fig.text(0.02, 0.02, f'数据来源: 香港各区疫情数据 | 生成时间: {pd.Timestamp.now().strftime("%Y-%m-%d %H:%M")}', 
                fontsize=8, style='italic', color='#666666')
        
        plt.tight_layout()
        plt.subplots_adjust(top=0.92, bottom=0.08)
        plt.savefig('香港疫情数据_各区对比图.png', dpi=300, bbox_inches='tight', 
                   facecolor='#f8f9fa', edgecolor='none')
        print("✅ 各区对比图表已保存为: 香港疫情数据_各区对比图.png")
        plt.show() 